package org.bet.domain;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.bet.domain.BioFeatureSet.FeatureType;
import org.bet.utils.Range;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.util.Assert;

@Document
@CompoundIndexes({
	@CompoundIndex(name = "name_idx", def = "{'ownerId': 1, 'name': 1}, {unique: true}"),
	@CompoundIndex(name = "region_idx", def = "{'assembly.id': 1, 'strand': 1, 'region.start': 1, 'region.end': 1}, {unique: true}")
})
public class BioFeatureEntry extends AbstractIDAssignedObject{
	private static final long serialVersionUID = -2411919763027770247L;
	
	@Indexed
	private String name;
	
	@Indexed
	private String ownerId;
	private String description;

	@DBRef
	private Assembly assembly;
	
	@Indexed
	private FeatureType type;
	
	private String strand; // '+', '-', or '.'
	private Range region;
	
	private double score;  // E-value or intensity of a data value
	
	public static final String REF_ATTR_KEY_PROTEIN_ID = "proteinId";
	public static final String REF_ATTR_KEY_ALIGN_ID = "alignId";

	private Map<String, String> refAttrMap = new HashMap<String, String>();
	
	@DBRef
	private Set<BioFeatureEntry> parents = new HashSet<BioFeatureEntry>();


	BioFeatureEntry(){
		super();
	}
	
	public BioFeatureEntry(String name, String ownerId){
		super(generateId(name, ownerId));
		
		Assert.hasText(name, "name should be not empty");
		Assert.hasText(ownerId, "ownerId should be not empty");
		
		this.name = name;
		this.ownerId = ownerId;
	}

	public String getName() {
		return name;
	}

//	public void setName(String name) {
//		this.name = name;
//	}

	public String getOwnerId() {
		return ownerId;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Assembly getAssembly() {
		return assembly;
	}

	public void setAssembly(Assembly assembly) {
		this.assembly = assembly;
	}

	public FeatureType getType() {
		return type;
	}

	public void setType(FeatureType type) {
		this.type = type;
	}

	public Range getRegion() {
		return region;
	}

	public void setRegion(Range region) {
		this.region = region;
	}

	public String getStrand() {
		return strand;
	}

	public void setStrand(String strand) {
		this.strand = strand;
	}
	
	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}

	public Set<BioFeatureEntry> getParents() {
		return parents;
	}

	public void setParents(Set<BioFeatureEntry> parents) {
		this.parents = parents;
	}


	protected static String generateId(String name, String ownerId) {
		return ownerId + ":" + name;
	}

	public void addRefAttribute(String attrId, String attrValue) {
		if(refAttrMap == null){
			refAttrMap = new HashMap<String, String>();
		}
		refAttrMap.put(attrId, attrValue);
	}
	
	@Override
	public String toString(){
		return ToStringBuilder.reflectionToString(this);
	}
}
